using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Coding.Methods
{
    /// <summary>
    /// kodowanie podwojne gamma liczbe x kodujemy jako x+1, inaczej jedynki sie nie 
    /// da zakodowac
    /// </summary>
    public class DoubleGammaCoding : CodingMethod
    {
        public MyBitVector Compress(List<int> value)
        {
            MyBitVector result = new MyBitVector();
            EliasGammaCoding coding = new EliasGammaCoding();
            
            foreach (int x in value)
            {
                // tutaj kodujemy dlugosc czesci binarnej rowniez binarnie
                int len = (int)Math.Floor(Math.Log10(x+1) / Math.Log10(2.0));
                int len2 = (int)Math.Floor(Math.Log10(len) / Math.Log10(2.0));

                BitArray result2 = new BitArray(2*len2+1);
                result2 = coding.Compress(len);
                //zakoduj poczatek
                for (int i = 0; i < result2.Count; i++)
                    result.Append(result2[i]);

                result.Append(true);

                for (int i = 0; i < len; i++)
                    if (((x+1) & (1 << (len - 1 - i))) != 0)
                        result.Append(true);
                    else
                        result.Append(false);
            }
            return result;
        }

        public List<int> Decompress(MyBitVector array)
        {
            List<int> result = new List<int>();

            int index = 0;
            int countZeroes;
            int len;
            int x;

            while (index < array.Length)
            {
                countZeroes = 0;
                len = 0;
                x = 0;
                while (array[index++] == false)
                {
                    if (index == array.Length)
                        return result;
                    countZeroes++;
                }

                len = (1 << countZeroes);
                while (--countZeroes >= 0)
                    if(array[index++] == true)
                        len += (1 << countZeroes);

                x += (1 << len);
                while (--len >= 0)
                    if (array[++index] == true)
                        x += (1 << len);

                index++;
                result.Add(x-1);
            }
            return result;
        }
    }
}
